package work.huangxin.share.controller.talk;

import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import work.huangxin.share.constant.RedisConstant;
import work.huangxin.share.domain.other.*;
import work.huangxin.share.service.impl.*;
import work.huangxin.share.util.CheckAllow;
import work.huangxin.share.util.CheckMessageUtil;
import work.huangxin.share.util.RedisUtil;
import work.huangxin.share.util.ThreadLocalUtil;
import work.huangxin.share.util.status.BaseResponse;
import work.huangxin.share.util.status.CodeEnum;
import work.huangxin.share.util.status.ResponseData;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

@RestController
@RequestMapping("/wx")
public class ArticleOperationController {

    @Resource
    private ArticleOperationService articleOperationService;
    @Resource
    private UserMessageOperationService userMessageOperationService;
    @Resource
    private CommentService commentService;
    @Resource
    private ReplayMessageOperationService replayMessageOperationService;
    @Resource
    private LikeArticleService likeArticleService;
    @Resource
    private NoticeOperationService noticeOperationService;
    @Resource
    private WXMessage wxMessage;

    @Resource
    private RedisUtil redisUtil;

    @Autowired
    private CheckAllow check;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @PostMapping("/saveArticle")
    @Transactional
    @ApiOperation(value = "保存文章")
    public BaseResponse saveArticle(@RequestBody ArticleMessage articleMessage, HttpServletRequest request) {
        Integer userId = check.checkAllow(userMessageOperationService, request);
        if (userId < 0) {
            return ResponseData.out(CodeEnum.SIGNATURE_NOT_ALLOW);
        }
        if (CheckMessageUtil.checkMessage(articleMessage.getArticleContent(), wxMessage)) {
            return ResponseData.error(403, "检测到内容违规,请重新输入");
        }
        articleMessage.setUserId(userId);
        articleOperationService.add(articleMessage);
        return ResponseData.success();
    }


    @PostMapping("/deleteArticle/{articleId}")
    @Transactional
    @ApiOperation(value = "删除文章")
    public BaseResponse deleteArticle(@PathVariable Integer articleId, HttpServletRequest request) {
        Integer userId = check.checkAllow(userMessageOperationService, request);

        if (userId < 0) {
            return ResponseData.out(CodeEnum.SIGNATURE_NOT_ALLOW);
        }
        ArticleMessage articleMessage = new ArticleMessage();

        articleMessage.setArticleId(articleId);
        articleMessage.setUserId(userId);
        articleOperationService.delete(articleMessage);

        CommentMessage commentMessage = new CommentMessage();
        commentMessage.setArticleId(articleId);
        List<CommentMessage> list = commentService.findList(commentMessage);

        ReplayMessage replayMessage = new ReplayMessage();
        for (int i = 0; i < list.size(); i++) {
            replayMessage.setCommentId(list.get(i).getCommentId());
            replayMessageOperationService.delete(replayMessage);
        }
        commentService.delete(commentMessage);

        NoticeMessage noticeMessage = new NoticeMessage();
        noticeMessage.setArticleId(articleId);
        noticeOperationService.delete(noticeMessage);

        return ResponseData.success();
    }

    @PostMapping("/deleteComment/{commentId}")
    @Transactional
    @ApiOperation(value = "删除评论")
    public BaseResponse deleteComment(@PathVariable Integer commentId, HttpServletRequest request) {
        Integer userId = check.checkAllow(userMessageOperationService, request);
        CommentMessage commentMessage = new CommentMessage();
        commentMessage.setCommentId(commentId);
        commentMessage.setUserId(userId);


        //查找评论中文章的id

        /**
         * 删除评论自动更新->评论量
         */
        Integer articleId = commentService.getArticleId(commentId);
        ArticleMessage newArticle = articleOperationService.getById(articleId);
        commentService.delete(commentMessage);
        newArticle.setTotalComment(commentService.getTotalComment(articleId));
        redisUtil.del(RedisConstant.articleById + commentMessage.getArticleId());
        redisUtil.set(RedisConstant.articleById + commentMessage.getArticleId(), newArticle);

        threadPoolExecutor.execute(() -> {
            articleOperationService.update(newArticle);
        });


        NoticeMessage noticeMessage = new NoticeMessage();
        noticeMessage.setCommentId(commentId);

        noticeOperationService.delete(noticeMessage);


        ReplayMessage replayMessage = new ReplayMessage();
        replayMessage.setCommentId(commentId);

        List<ReplayMessage> list = replayMessageOperationService.findList(replayMessage);

        replayMessageOperationService.delete(replayMessage);

        for (int i = 0; i < list.size(); i++) {
            NoticeMessage noticeMessage1 = new NoticeMessage();
            noticeMessage1.setReplayId(list.get(i).getReplayId());
            noticeOperationService.delete(noticeMessage1);
        }


        return ResponseData.success();
    }

    /**
     * @param replayId 这个就是留下回复的 userId，而不是replay_message中的 replay_id
     * @param request
     * @return
     */
    @PostMapping("/deleteReplay/{replayId}")
    @Transactional
    @ApiOperation(value = "删除回复")
    public BaseResponse deleteReplay(@PathVariable Integer replayId, HttpServletRequest request) {
        WXSessionModel user = (WXSessionModel) request.getSession().getAttribute("user");
        Long userId = ThreadLocalUtil.get();
        WXSessionModel user1 = (WXSessionModel) redisUtil.get("user:" + userId);
        ReplayMessage message = replayMessageOperationService.getReplayMessage(replayId);


        ReplayMessage replayMessage = new ReplayMessage();
        replayMessage.setReplayId(replayId);
        replayMessage.setUserId(user.getUserId());
        replayMessageOperationService.deleteById(replayMessage);


        //TODO 删除评论，则总评论数 - 1，再去数据库中查询
        Integer commentId = message.getCommentId();
        Integer articleId = commentService.getArticleId(commentId);
        ArticleMessage newArticleById = articleOperationService.getNewArticleById(articleId);
        newArticleById.setTotalComment(commentService.getTotalComment(articleId) + commentService.getReplyComment(commentId));

        articleOperationService.update(newArticleById);


        NoticeMessage noticeMessage = new NoticeMessage();
        noticeMessage.setReplayId(replayId);
        noticeOperationService.delete(noticeMessage);

        return ResponseData.success();
    }

    @GetMapping("/getLikeArticle/{articleId}")
    @Transactional
    @ApiOperation(value = "检测文章是否被喜欢")
    public BaseResponse getLikeArticle(@PathVariable Integer articleId, HttpServletRequest request) {
        WXSessionModel user = (WXSessionModel) request.getSession().getAttribute("user");
        Long userId = ThreadLocalUtil.get();
        WXSessionModel user1 = (WXSessionModel) redisUtil.get("user:" + userId);
        LikeMessage likeMessage = new LikeMessage();
        likeMessage.setArticleId(articleId);
        likeMessage.setUserId(user.getUserId());

        Integer count = likeArticleService.findCount(likeMessage);
        if (count == 0) {
            return ResponseData.success(false);
        }
        return ResponseData.success(true);
    }
    @GetMapping("/getUserLikeArticles")
    public BaseResponse getUserLikeArticles(HttpServletRequest request) {
        //获得点赞改篇文章的用户id，并且检查用户是否被封禁
        Integer userId = check.checkAllow(userMessageOperationService, request);
        //userId异常
        if (userId < 0) {
            return ResponseData.out(CodeEnum.BODY_NOT_MATCH, "用户信息异常");
        }
        List<Object> list = redisUtil.getCacheList(RedisConstant.USER_LIKE_TIME + userId);
        return ResponseData.success(list);
    }

    /**
     * 新版点赞文章
     *
     * @return
     */
    //@PutMapping("/likesArticle/{id}")
    //@Transactional
    //public BaseResponse likeArticleNew(@PathVariable Integer id,HttpServletRequest request){
    //    //获得点赞改篇文章的用户id，并且检查用户是否被封禁
    //    Integer userId = CheckAllow.checkAllow(userMessageOperationService, request);
    //    //userId异常
    //    if (userId < 0){
    //        return ResponseData.out(CodeEnum.BODY_NOT_MATCH,"用户信息异常");
    //    }
    //    //TODO 从redis中获得数据，并且可以使用异步双写
    //    //从数据库中获得article
    //    ArticleMessage articleMessageByLike = articleOperationService.getById(id);
    //    if (Objects.isNull(articleMessageByLike)){
    //        return ResponseData.out(CodeEnum.NOT_FOUND,"文章可能已经被删除");
    //    }
    //    //点赞数+1
    //    //TODO 考虑使用分布式锁
    //    articleMessageByLike.setTotalLikes(articleMessageByLike.getTotalLikes() + 1);
    //    //TODO 发送消息 告知用户被点赞
    //    return ResponseData.success();
    //}
    @GetMapping("/likeArticle/{articleId}")
    @Transactional
    @ApiOperation(value = "喜欢文章")
    public BaseResponse LikeArticle(@PathVariable Integer articleId, HttpServletRequest request) {
        Integer userId = check.checkAllow(userMessageOperationService, request);
        if (userId < 0) {
            return ResponseData.out(CodeEnum.SIGNATURE_NOT_ALLOW);
        }

        //先获取当前位置的bit状态 1为喜欢 0为不喜欢
        boolean bit = redisUtil.getBit
                (RedisConstant.USER_LIKE_ARTICLE + userId, Long.valueOf(articleId));
        //设定喜欢的文章 设定状态为相反
        redisUtil.setBit(RedisConstant.USER_LIKE_ARTICLE + userId,
                Long.valueOf(articleId), !bit);

        List<Long> likeList = redisUtil.getCacheList(
                RedisConstant.USER_LIKE_TIME + userId);
        if (bit) {
            likeList.remove(articleId);
        } else {
            likeList.add(Long.valueOf(articleId));
        }
        //去重后放入list
        ArrayList<Long> likeList1 = new ArrayList<>(new HashSet<Long>(likeList));
        redisUtil.del(RedisConstant.USER_LIKE_TIME + userId);
        if (!likeList1.isEmpty()) {
            redisUtil.setCacheList(RedisConstant.USER_LIKE_TIME + userId,
                    new ArrayList<>(new HashSet<>(likeList)));
        }

        //用线程池去跑这个任务
        threadPoolExecutor.execute(() -> {

            LikeMessage likeMessage = new LikeMessage();

            likeMessage.setArticleId(articleId);
            likeMessage.setUserId(userId);
            //去数据库中查找这个用户是否给这篇文章点赞
            List<LikeMessage> list = likeArticleService.findList(likeMessage);
            if (list.size() == 0) {
                //没有点过赞，做点赞操作
                likeArticleService.add(likeMessage);
                LikeMessage likeMessage1 = likeArticleService.findList(likeMessage).get(0);

                ArticleMessage newArticleById = articleOperationService.getNewArticleById(articleId);

                NoticeMessage noticeMessage = new NoticeMessage();

                noticeMessage.setArticleId(articleId);

                noticeMessage.setNoticeType(2);
                noticeMessage.setUserId(newArticleById.getUserId());
                noticeMessage.setLikeId(likeMessage1.getLikeId());

                List<NoticeMessage> noticeMessages = noticeOperationService.findList(noticeMessage);

                if (noticeMessages.size() == 0 && !newArticleById.getUserId().equals(userId)) {

                    noticeMessage.setLikeId(likeMessage1.getLikeId());
                    noticeOperationService.add(noticeMessage);
                }
                //TODO 从数据库中获得总点赞量更为可靠
                newArticleById.setTotalLikes(newArticleById.getTotalLikes() + 1);
                articleOperationService.update(newArticleById);
            } else {
                //已经点赞表示取消
                ArticleMessage newArticleById = articleOperationService.getNewArticleById(articleId);

                NoticeMessage noticeMessage = new NoticeMessage();

                noticeMessage.setArticleId(articleId);

                noticeMessage.setNoticeType(2);
                noticeMessage.setUserId(newArticleById.getUserId());
                noticeMessage.setLikeId(list.get(0).getLikeId());

                likeArticleService.delete(likeMessage);
                noticeOperationService.delete(noticeMessage);
                //点赞量不需要高数据一致性要求，不需要一定从数据库中查询总数量
                newArticleById.setTotalLikes(newArticleById.getTotalLikes() > 0 ? (newArticleById.getTotalLikes() - 1)
                        : 0);
                articleOperationService.update(newArticleById);
            }
        });

        return ResponseData.success();
    }

    @PostMapping("/checkArticle/{articleId}")
    @Transactional
    @ApiOperation("举报文章")
    public BaseResponse checkArticle(@PathVariable Integer articleId, HttpServletRequest request) {
        UserMessage userMessage = new UserMessage();
        userMessage.setUserAdmin("2");

        //拿到请求用户的userId
        Integer userId = check.checkAllow(userMessageOperationService, request);

        if (userId < 0) {
            return ResponseData.out(CodeEnum.SIGNATURE_NOT_ALLOW);
        }

        //拿到user_message的所有信息
        List<UserMessage> list = userMessageOperationService.findList(userMessage);

        for (int i = 0; i < list.size(); i++) {
            NoticeMessage noticeMessage = new NoticeMessage();
            noticeMessage.setContent("我举报这篇文章,查看详情");
            noticeMessage.setNoticeType(6);
            noticeMessage.setArticleId(articleId);
            noticeMessage.setSendUserId(userId);
            noticeMessage.setUserId(list.get(i).getUserId());
            noticeOperationService.add(noticeMessage);
        }
        return ResponseData.success();
    }



}
